using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Shape;
using GameCamera;
using Light;

namespace CGEx4
{

  public class Game1 : Microsoft.Xna.Framework.Game
  {
    GraphicsDeviceManager graphics;
    Camera mainCamera;
    Vector3[] lights;
    List<IShape> shapes;
    IShape skyBox;
    KeyboardState oldState;
    TextureCube skyTexture, floorTexture;
    LightPoint light;
    SpriteBatch spriteBatch;

    public Game1()
    {
      graphics = new GraphicsDeviceManager(this);
      graphics.PreferredBackBufferWidth = GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Width;
      graphics.PreferredBackBufferHeight = GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Height;
      graphics.IsFullScreen = true;
      Content.RootDirectory = "Content";
    }

    protected override void Initialize()
    {
      oldState = Keyboard.GetState();
      Content.RootDirectory = "Content";
      mainCamera = new Camera(true, new Vector3(0.0f, 0.0f, 8.0f), GraphicsDevice.Viewport);
      lights = new Vector3[3];
      shapes = new List<IShape>();
      base.Initialize();
    }

    protected override void LoadContent()
    {
      spriteBatch = new SpriteBatch(GraphicsDevice);
      Effect poolEffect = Content.Load<Effect>("Pool");
      Effect skyEffect = Content.Load<Effect>("Pool");
      Effect bottomEffect = Content.Load<Effect>("Pool");
      var noiseTexture = Content.Load<Texture2D>("noise_water");
      skyTexture = Content.Load<TextureCube>("SkyBox");
      floorTexture = Content.Load<TextureCube>("tiles");    
      light = new LightPoint(mainCamera, poolEffect, Color.White.ToVector4(), 0.5f,
        new Vector3(0.0f, 20.0f, 80.0f), Color.White.ToVector4(), new Vector3(0.0f, -20.0f, -20.0f), floorTexture);
      IShape skyBox = new Cube(new Vector3(0.0f, 0.0f, 0.0f), 300.0f, graphics.GraphicsDevice, poolEffect, null, skyTexture);
      IShape plane = new Shape.Plane(new Vector3(0.0f, -10.0f, 0.0f), 300.0f, graphics.GraphicsDevice, poolEffect, noiseTexture, skyTexture);
      this.skyBox = skyBox;
      skyBox.Effect = skyEffect;
      shapes.Add(plane);
      foreach (var shape in shapes)
        shape.Effect.CurrentTechnique = light.LightingEffect.Techniques["ReflectionTechnique"];
        
    }

    private void InputDetection()
    {
      KeyboardState keyboardState = Keyboard.GetState();
      if (keyboardState.IsKeyDown(Keys.Escape))
        this.Exit();
      oldState = keyboardState;
    }

    protected override void Update(GameTime gameTime)
    {
      InputDetection();
      mainCamera.Update();
      light.Update();
      base.Update(gameTime);
    }

    protected override void Draw(GameTime gameTime)
    {
      GraphicsDevice.Clear(Color.Black);
      light.LightingEffect.Parameters["time"].SetValue((float)gameTime.TotalGameTime.TotalMilliseconds);
      GraphicsDevice.RasterizerState = RasterizerState.CullClockwise;
      drawCube(skyBox, mainCamera, "SkyBoxTechnique");
      GraphicsDevice.RasterizerState = RasterizerState.CullCounterClockwise;
      drawAll(mainCamera);
      base.Draw(gameTime);
    }

    private void drawCube(IShape skyBox, Camera camera, string technique)
    {
      skyBox.Effect.CurrentTechnique = skyBox.Effect.Techniques[technique];
      skyBox.drawShape(mainCamera);
    }

    private void drawAll(Camera camera)
    {
      foreach (var shape in shapes)
      {
        shape.Effect.CurrentTechnique = light.LightingEffect.Techniques["ReflectionTechnique"];
        shape.drawShape(camera);
      }
    }
  }
}
